package com.yfs.cloud.aop;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
* @Company: 影法師工作室
* @Description: 自动打印进入和离开controller方法的日志切面  
* @author 影法師  
* @date 2020年8月24日 下午4:11:58 
* @version V1.0
 */
@Aspect
@Component
public class AutoLogAspect {
	private static final Logger logger = LoggerFactory.getLogger(AutoLogAspect.class);

	/**
	 * 切入点组件, com.yfs.cloud.controller 包下的所有类的所有方法(任何入参)
	 */
	@Pointcut("execution(public * com.yfs.cloud.controller.*.*(..))")
	public void autoLog() {
	}

	/**
	 * 前置通知
	 * 
	 * @param joinPoint
	 * @throws Throwable
	 */
	@Before("autoLog()")
	public void doBefore(JoinPoint joinPoint) {
		// 其实实际项目开发的时候, 这里也是要存储到mongodb、redis之类的nosql中去的. 但是一般存半年之后数据迁移
		// 云备份(防止后面又有人需要查,例如公安)
		// 接收到请求，记录请求内容
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		// 记录下请求内容
		logger.info("请求URI : {}, 请求方法 : {}, 客户端IP : {}", request.getRequestURI(), request.getMethod(),
				request.getRemoteAddr());
		String queryString = request.getQueryString();
		if (StringUtils.isNotBlank(queryString)) {
			logger.info("查询字符串 : {}", queryString);
		}
		Enumeration<String> enu = request.getParameterNames();
		// 打印请求入参
		while (enu.hasMoreElements()) {
			String name = enu.nextElement();
			logger.info("name:{},value:{}", name, request.getParameter(name));
		}
	}

	/**
	 * 正常返回通知
	 * 
	 * @param ret
	 */
	@AfterReturning(returning = "ret", pointcut = "autoLog()")
	public void doAfterReturning(Object ret) {
		// 处理完请求，返回内容
		logger.info("请求结束, 服务端响应 : {}", ret);
	}
}
